package server;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.SocketException;
import java.util.ArrayDeque;
import java.util.Deque;

import lib.Commands;
import lib.Universe;

public class TCPServer extends Thread {
	private static ServerSocket serverSocket;
	public static Deque<TCPServerUnit> Units = new ArrayDeque<TCPServerUnit>();
	public static boolean run = true;
	private static String password = "simsalabim";
	private int PORT = 0;
	static BufferedWriter log = null;

	public TCPServer(int PORT) {
		this.PORT = PORT;
		this.start();
		try {
			log = new BufferedWriter(new FileWriter("log.txt"));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Send messages to all server-threads.
	 * 
	 * @param commands
	 */
	public static void broadcast(Commands commands, String s) {
		for (TCPServerUnit u : Units) {
			u.send(commands, s, false);
			log("Server", commands + " " + s);
		}
	}

	public static void Error(Exception e) {
		log("Server", "Server Error!");
		e.printStackTrace();
		System.exit(-1);

	}

	public static boolean Password(String arg) {
		if (arg.equals(password))
			return true;
		return false;
	}

	public static void log(String src, String s) {
		try {
			log.write(lib.Utils.TimeStamp() + src + " " + s + "\n");
			log.flush();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * To stop the server. Should not be accessed by TCPServerUnit.
	 * 
	 * @param serverUnit
	 */
	public static void stop(TCPServerUnit serverUnit) {

		for (int i = 0; i < 5; i++) {
			try {
				broadcast(Commands.PRINT, "Server shut down in "
						+ (10 - (2 * i)) + "s...");
				Thread.sleep(1000);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
		}
		for (TCPServerUnit u : Units) {
			if (u != serverUnit)
				u.Unitstop();
		}
		try {
			serverUnit.Unitstop();
			serverSocket.close();
			log.close();
			System.exit(0);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void run() {
		System.out.println("Server Startet.");
		HighScore.initHighScore();
		try {
			serverSocket = new ServerSocket(PORT);
			new Ping();
			while (run) {
				TCPServerUnit temp = new TCPServerUnit(serverSocket.accept());
				Units.push(temp);
				log("Server", "ServerUnit: "
						+ Units.getFirst().socket.getInetAddress().toString()
						+ " created.");
				log("Server", "Deque Size: " + Units.size());
				Units.getFirst().start();

				if (GamesList.gamesList == null)
					GamesList.initList();
				if (GamesList.gamesList.size() == 0)
					GamesList.gamesList.put(Units.size(), new Universe(Units
							.size(),"robo.map"));

			}
		} catch (SocketException e) {
			log("Server", "Socket Closed!");
			System.exit(-1);
		} catch (IOException e) {
			Error(e);
		} finally {
			try {
				serverSocket.close();
				log("Server", "Server stoped");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
